﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using CommandLine;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using Path = System.IO.Path;
using ProgressBar = System.Windows.Controls.ProgressBar;

namespace UIWPF
{
    /// <summary>
    /// Interaction logic for FolderCompareWindow.xaml
    /// </summary>
    public partial class FolderCompareWindow : Window
    {
        private bool _tmFlag = true;
        private bool _doHiding = false;
        private DispatcherTimer tm = new DispatcherTimer();
        private string m_ExcelFile = "";

        public FolderCompareWindow()
        {
            InitializeComponent();

            tm.Tick += TickGradual;
            tm.Interval = TimeSpan.FromSeconds(0.01);
        }

        private void TickGradual(object sender, EventArgs e)
        {
            if (_tmFlag)
            {
                Opacity += 0.02;
                if (Opacity >= 1.0)
                {
                    tm.Stop();
                }
            }
            else
            {
                Opacity -= 0.02;
                if (Opacity <= 0.0)
                {
                    if (_doHiding)
                    {
                        tm.Stop();
                        Hide();
                    }
                    else
                    {
                        Close();
                    }
                }
            }
        }

        private void doOpening()
        {
            Show();
            Opacity = 0.0;
            _tmFlag = true;
            tm.Start();
        }
        private void doClosing()
        {
            _doHiding = false;
            _tmFlag = false;
            tm.Start();
        }
        private void doHiding()
        {
            _doHiding = true;
            _tmFlag = false;
            tm.Start();
        }

        private void FormLoading(object sender, RoutedEventArgs e)
        {
            Opacity = 0;
//            tbFolderPath.Text = @"D:\CodeSimilarity\Test";
            doOpening();
        }

        private void DragWindowMouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                DragMove();
            }
        }

        private void BtnExitClick(object sender, RoutedEventArgs e)
        {
            doClosing();
        }

        private void BtnChooseFolderClick(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "Please choose the codes folder";
            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                tbFolderPath.Text = fbd.SelectedPath;
            }
        }

        private void btnEnterClick(object sender, RoutedEventArgs e)
        {
            if (cb1vsN.IsChecked == true)
            {
                doComparing(tbFilePath.Text, tbFolderPath.Text);
            }
            else
            {
                doComparing(tbFolderPath.Text);
            }
        }

        private void tbFolderPathKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                doComparing(tbFolderPath.Text);
            }
        }

        private void doComparing(string filePath, string folderPath)
        {
            if (!File.Exists(@filePath))
            {
                MyMessageBox.Show("Error", "File doesn't exist.", false);
                return;
            }
            if (!Directory.Exists(@folderPath))
            {
                MyMessageBox.Show("Error", "Folder doesn't exist.", false);
                return;
            }

            // lock the buttons
            btnOpenExcel.IsEnabled = false;
            btnChooseFile.IsEnabled = false;
            btnChooseFolder.IsEnabled = false;
            btnEnter.IsEnabled = false;

            tbxOutput.Text = "";
            double val = 0;
            FolderComparer fc = new FolderComparer(@folderPath);
            List<string> fileList = fc.GetCodeFiles();
            List<string> fileNameList = new List<string>();
            List<string> resList = new List<string>();
            resList.Add(Path.GetFileName(filePath));
            for (int i = 0; i < fileList.Count; i++)
            {
                fileNameList.Add(Path.GetFileName(fileList[i]));
            }
            DataTable[] dtCompareResult = new DataTable[8];
            string[] dataTableNames = new string[]
                                          {
                                              "TextDiff", "ListDiff -Headers", "ListDiff -Namespaces", "ListDiff -Words",
                                              "ListDiff -Symbols", "ListDiff -Body", "Asm -Operand", "Asm -Instruction"
                                          };
            for (int i = 0; i < dtCompareResult.Length; i++)
            {
                /*
                 * 0 - TextDiff
                 * 1 - ListDiff: Headers
                 * 2 = ListDiff: Namespaces
                 * 3 - ListDiff: Words
                 * 4 - ListDiff: Symbols
                 * 5 - ListDiff: Body
                 * 6 - Asm: Operand
                 * 7 - Asm: Instruction
                 */
                dtCompareResult[i] = ExcelUtility.InitDataTable(dataTableNames[i], fileNameList, resList);
            }

            Action<DependencyProperty, double> UpdateProgressbarValue = (dp, value) => pbCompareProgress.SetValue(dp, value);
            pbCompareProgress.Minimum = 0;
            pbCompareProgress.Maximum = fileList.Count + 1;
            pbCompareProgress.Value = 0;
            pbCompareProgress.Visibility = Visibility.Visible;
            lblProgreeValue.Content = "进度: 0%";
            lblProgreeValue.Visibility = Visibility.Visible;

            for (int i = 0; i < fileList.Count; i++)
            {
                StringBuilder output = new StringBuilder();
                List<CommandLine.Degree> lcd = CommandLine.CompareManager.Compare(filePath, fileList[i], ref output);

                for (int k = 0; k < lcd.Count; k++ )
                {
                    string strDeg = (lcd[k].degMixed != -1 ? (lcd[k].degMixed * 100.0).ToString() + "%" : "Crushed.");
                    ExcelUtility.EditDataTable(ref dtCompareResult[k], i + 1, 0, strDeg);
                }

                tbxOutput.Text += output.ToString();
                Console.WriteLine(tbxOutput.Text.Length);
                if (tbxOutput.Text.Length > 32768)
                {
//                    Console.WriteLine("Clear.");
                    tbxOutput.Text = "";
                }
                tbxOutput.ScrollToEnd();
                val++;
                Dispatcher.Invoke(UpdateProgressbarValue,
                                System.Windows.Threading.DispatcherPriority.Background,
                                ProgressBar.ValueProperty, val);
                double tmp = pbCompareProgress.Value / pbCompareProgress.Maximum * 100.0;
                lblProgreeValue.Content = String.Format("进度: {0:N2}%", tmp);
            }

            DataSet ds = new DataSet();
            for (int i = 0; i < dtCompareResult.Length; i++)
            {
                ds.Tables.Add(dtCompareResult[i]);
            }
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "Save xlsx file.";
            sfd.Filter = "Excel File (*.xlsx) | *.xlsx";
            sfd.FileName = "CR" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string savePath = sfd.FileName;
                string saveResult = ExcelUtility.ExportToExcel(ds, savePath);
                tbxOutput.Text += "Save compare results to excel file: " + savePath + "\n";

                if (!saveResult.Equals("success"))
                {
                    tbxOutput.Text += "Saving excel crushed, might due to: " + saveResult + "\n";
                }
                else
                {
                    tbxOutput.Text += "Saving completed.\n";
                    m_ExcelFile = savePath;
                }
                btnOpenExcel.IsEnabled = true;
                tbxOutput.ScrollToEnd();
            }
            else
            {
                btnOpenExcel.IsEnabled = false;
            }
            lblProgreeValue.Content = String.Format("进度: 100%");

            val++;
            Dispatcher.Invoke(UpdateProgressbarValue,
                              System.Windows.Threading.DispatcherPriority.Background,
                              ProgressBar.ValueProperty, val);

            // free the buttons
            btnChooseFile.IsEnabled = true;
            btnChooseFolder.IsEnabled = true;
            btnEnter.IsEnabled = true;

            GC.Collect();
        }

        private void doComparing(string folderPath)
        {
            if (!Directory.Exists(@folderPath))
            {
                MyMessageBox.Show("Error", "Folder doesn't exist.", false);
                return;
            }

            // lock the buttons
            btnOpenExcel.IsEnabled = false;
            btnChooseFile.IsEnabled = false;
            btnChooseFolder.IsEnabled = false;
            btnEnter.IsEnabled = false;

            tbxOutput.Text = "";
            double val = 0;
            FolderComparer fc = new FolderComparer(@folderPath);
            List<string> fileList = fc.GetCodeFiles();
            List<string> fileNameList = new List<string>();
            for (int i = 0; i < fileList.Count; i++)
            {
                fileNameList.Add(Path.GetFileName(fileList[i]));
            }

            DataTable[] dtCompareResult = new DataTable[8];
            string[] dataTableNames = new string[]
                                          {
                                              "TextDiff", "ListDiff -Headers", "ListDiff -Namespaces", "ListDiff -Words",
                                              "ListDiff -Symbols", "ListDiff -Body", "Asm -Operand", "Asm -Instruction"
                                          };
            for (int i = 0; i < dtCompareResult.Length; i++)
            {
                /*
                 * 0 - TextDiff
                 * 1 - ListDiff: Headers
                 * 2 = ListDiff: Namespaces
                 * 3 - ListDiff: Words
                 * 4 - ListDiff: Symbols
                 * 5 - ListDiff: Body
                 * 6 - Asm: Operand
                 * 7 - Asm: Instruction
                 */
                dtCompareResult[i] = ExcelUtility.InitDataTable(dataTableNames[i], fileNameList, fileNameList);
            }

            Action<DependencyProperty, double> UpdateProgressbarValue = (dp, value) => pbCompareProgress.SetValue(dp, value);
            pbCompareProgress.Minimum = 0;
            pbCompareProgress.Maximum = fileList.Count*(fileList.Count - 1)/2.0 + 1;
            pbCompareProgress.Value = 0;
            pbCompareProgress.Visibility = Visibility.Visible;
            lblProgreeValue.Content = "进度: 0%";
            lblProgreeValue.Visibility = Visibility.Visible;

            for (int i = 0; i < fileList.Count; i++)
            {
                for (int j = i + 1; j < fileList.Count; j++)
                {
                    StringBuilder output = new StringBuilder();
                    List<CommandLine.Degree> lcd = CommandLine.CompareManager.Compare(fileList[i], fileList[j], ref output);

                    for (int k = 0; k < dtCompareResult.Length; k++)
                    {
                        string strDeg = (lcd[k].degMixed != -1 ? (lcd[k].degMixed * 100.0).ToString() + "%" : "Crushed.");
                        ExcelUtility.EditDataTable(ref dtCompareResult[k], i + 1, j, strDeg);
                    }

                    tbxOutput.Text += output.ToString();
                    Console.WriteLine(tbxOutput.Text.Length);
                    if (tbxOutput.Text.Length > 32768)
                    {
//                        Console.WriteLine("Clear.");
                        tbxOutput.Text = "";
                    }
                    tbxOutput.ScrollToEnd();
                    val++;
                    Dispatcher.Invoke(UpdateProgressbarValue,
                                    System.Windows.Threading.DispatcherPriority.Background,
                                    ProgressBar.ValueProperty, val);
                    double tmp = pbCompareProgress.Value / pbCompareProgress.Maximum * 100.0;
                    lblProgreeValue.Content = String.Format("进度: {0:N2}%", tmp);
                }
            }

            DataSet ds = new DataSet();
            for (int i = 0; i < dtCompareResult.Length; i++)
            {
                ds.Tables.Add(dtCompareResult[i]);
            }

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "Save xlsx file.";
            sfd.Filter = "Excel File (*.xlsx) | *.xlsx";
            sfd.FileName = "CR" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string savePath = sfd.FileName;
                string saveResult = ExcelUtility.ExportToExcel(ds, savePath);
                tbxOutput.Text += "Save compare results to excel file: " + savePath + "\n";

                if (!saveResult.Equals("success"))
                {
                    tbxOutput.Text += "Saving excel crushed, might due to: " + saveResult + "\n";
                }
                else
                {
                    tbxOutput.Text += "Saving completed.\n";
                    m_ExcelFile = savePath;
                }
                btnOpenExcel.IsEnabled = true;
                tbxOutput.ScrollToEnd();
            }
            else
            {
                btnOpenExcel.IsEnabled = false;
            }

//            string savePath = tbFolderPath.Text + "\\CR" + DateTime.Now.ToString("hhmmssddmmyyyy") + ".xlsx";

            lblProgreeValue.Content = String.Format("进度: 100%");

            val++;
            Dispatcher.Invoke(UpdateProgressbarValue,
                              System.Windows.Threading.DispatcherPriority.Background,
                              ProgressBar.ValueProperty, val);

            btnChooseFile.IsEnabled = true;
            btnChooseFolder.IsEnabled = true;
            btnEnter.IsEnabled = true;

            GC.Collect();
        }

        private void CB1vsNGotFocused(object sender, RoutedEventArgs e)
        {
            if (cb1vsN.IsChecked == false)
            {
                lblFilePath.Visibility = Visibility.Visible;
                tbFilePath.Visibility = Visibility.Visible;
            }
        }

        private void CB1vsNLostFocused(object sender, RoutedEventArgs e)
        {
            if (cb1vsN.IsChecked == false)
            {
                lblFilePath.Visibility = Visibility.Hidden;
                tbFilePath.Visibility = Visibility.Hidden;
            }
        }

        private void cb1vsN_Checked(object sender, RoutedEventArgs e)
        {
            if (cb1vsN.IsChecked == false)
            {
                lblFilePath.Visibility = Visibility.Hidden;
                tbFilePath.Visibility = Visibility.Hidden;
                btnChooseFile.Visibility = Visibility.Hidden;
            }
            else if (cb1vsN.IsChecked == true)
            {
                lblFilePath.Visibility = Visibility.Visible;
                tbFilePath.Visibility = Visibility.Visible;
                btnChooseFile.Visibility = Visibility.Visible;
            }
        }

        private void BtnChooseFileClick(object sender, RoutedEventArgs e)
        {
            OpenFileDialog opd = new OpenFileDialog();
            opd.Title = "Choose File.";
            opd.Filter = "CPP file(*.cpp, *.h, *.txt)|*.cpp;*.h;*.txt";
            if (opd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                tbFilePath.Text = opd.FileName;
            }
        }

        private void BtnOpenExcelClick(object sender, RoutedEventArgs e)
        {
            tbxOutput.Text += "Open " + m_ExcelFile + "\n";
            tbxOutput.ScrollToEnd();
            try
            {
                System.Diagnostics.Process.Start(m_ExcelFile);
            }
            catch (Exception ex)
            {
                tbxOutput.Text += ex.Message + "\n";
                tbxOutput.ScrollToEnd();
            }
        }
    }
}
